package com.jt.www.queue.issue;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import com.jt.www.admin.user.service.UserService;
import com.jt.www.common.service.SendEmailsService;
import com.jt.www.dao.mapper.issue.EPolicyLogMapper;
import com.jt.www.dao.mapper.issue.EPolicyMapper;
import com.jt.www.dao.mapper.issue.mapper.IssuePolicyLogEntityMapper;
import com.jt.www.dao.mapper.issue.mapper.IssueRecordEntityMapper;
import com.jt.www.dao.mapper.issue.mapper.MqMessageEntityMapper;
import com.jt.www.enums.issue.IssueEnum;
import com.jt.www.model.issue.entity.IssuePolicyLogEntity;
import com.jt.www.model.issue.entity.IssueRecordEntity;
import com.jt.www.model.issue.entity.MqMessageEntity;
import com.jt.www.model.pol.FileInfoVO;
import com.jt.www.model.pol.UploadEndorsementCheckFile;
import com.jt.www.model.reps.GenericListResponse;
import com.jt.www.remote.DexClient;
import com.jt.www.remote.PolClient;
import com.jt.www.remote.ins.InsClient;
import com.jt.www.util.DateUtils;
import com.rabbitmq.client.Channel;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * @Description: 电子批单绑定
 * @author: xuxinku
 * @Date: 2019/11/22 14:01
 * @ModifiedDate：
 * @Copyright:江泰保险股份有限公司 1.监听消息对列获取xml信息，解析报文拼装参数，入库赋值初始状态
 * 2.请求数据交换中心接口获取资源ID，记录成功失败状态
 * 3.去批单中心绑定电子批单，记录成功失败状态
 */
@Component
public class ElecApprovalMsglistener {

    public static final Logger log = LoggerFactory.getLogger(ElecApprovalMsglistener.class);

    @Autowired
    EPolicyLogMapper ePolicyLogMapper;
    @Autowired
    EPolicyMapper ePolicyMapper;
    @Autowired
    DexClient dexClient;
    @Autowired
    InsClient insClient;
    @Autowired
    PolClient polClient;

    @Autowired
    IssueRecordEntityMapper issueRecordEntityMapper;
    @Autowired
    IssuePolicyLogEntityMapper issuePolicyLogEntityMapper;
    @Autowired
    MqMessageEntityMapper mqMessageEntityMapper;

    @Autowired
    private SendEmailsService emailsService;

    @Autowired
    private UserService userService;

    public static void main(String[] args) throws Exception {

        ElecApprovalMsglistener elecApprovalMsglistener = new ElecApprovalMsglistener();

        elecApprovalMsglistener.sendEmail("PD191120092027220805", "17", "20190516012");


    }

    private static Document loadConfig() {
        Document doc = null;
        SAXReader reader = new SAXReader();
        try {
            doc = reader.read("D:/Test/xml.xml");
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return doc;
    }

    // dev环境注释掉  test放开
    @RabbitListener(queues = "${jtpf.rabbit.queuename.endor}")
    public void processMsg(Message msg, Channel channel) {
        Long logId = System.currentTimeMillis();

        log.info("{}:ElecApprovalMsglistener get MessageProperties  {}", logId, msg.getMessageProperties().toString());
        log.info("{}:ElecApprovalMsglistener get MessageBody  {}", logId, new String(msg.getBody()));

        byte[] msgbody = msg.getBody();
        if (msgbody == null || msgbody.length == 0) {
            log.info("{}:返回报文为空 {} {}", logId, msg.getMessageProperties().getReceivedExchange(), msg.getMessageProperties().getReceivedRoutingKey());
            try {
                channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
            } catch (IOException e) {
                log.error("{}:ACK确认出错，出错信息为", logId, e);
            }
            return;
        }
        try {
            // 字节数组转换为输入流
            InputStream is = new ByteArrayInputStream(msgbody);
            // 解析xml
            SAXReader reader = new SAXReader();
            Document document = reader.read(is);
            Element rootElement = document.getRootElement();
            log.info("{}:解析的消息：{}", logId, rootElement.asXML());

            // 保险公司响应的报文
            boolean result = true;
            String ifCode = msg.getMessageProperties().getHeaders().get("IfCode").toString();
            //添加消息记录入库 并直接返回 ack
            MqMessageEntity mqMessageEntity = new MqMessageEntity();
            mqMessageEntity.setIfCode(ifCode);
            mqMessageEntity.setMessage(rootElement.asXML());
            mqMessageEntity.setCreateTime(new Date());
            mqMessageEntityMapper.insert(mqMessageEntity);
            //获取到ifCode是否是山东的，若山东的则都走一个方法
            if (isSdIssue(ifCode)) {
                result = processSD(rootElement, ifCode);
            }
            switch (ifCode) {
                case "20190516012":
                    //山东产品（山东省校（园）方责任保险项目）
                    result = processSD(rootElement, ifCode);
                    break;

                default:
                    log.error("{}:错误的批单ifCode {}", logId, ifCode);
            }
            if (!result) {
                //消息入库定时重试5次
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            log.error("{}:ElecApprovalMsglistener 出错，出错信息为", logId, ex);
        } finally {
            try {
                channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
            } catch (IOException e) {
                log.error("{}:ACK确认出错，出错信息为", logId, e);
            }
        }
    }

    public boolean isSdIssue(String ifCode) {
        List list = new ArrayList();
        list.add("20190516012"); //临沂
        if (list.contains(ifCode)) {
            return true;
        }
        return false;
    }

    /**
     * 山东产品（山东省校（园）方责任保险项目）
     *
     * @param rootElement
     * @return
     */
    private Boolean processSD(Element rootElement, String ifCode) {
        // 解析xml，封装数据
        Element reqPacket = getReqPacket(rootElement);
        Element respPacket = getRespPacket(rootElement);

        String proCode = IssueEnum.getProCodeByIfCode(ifCode);

        Element body = reqPacket.element("body");
        //产品公司code
        String companyCode = reqPacket.element("head").element("userId").getStringValue();
        String currentTime = DateUtils.getCurrentTime();
        // 批单申请号
        String pdNo = rootElement.element("ApplicationFormCode").getStringValue();
        // 批单号
        String policyNo = respPacket.element("body").element("apply").element("updateNo").getStringValue();
        // 入库
        // 入库之前首先判断 是否已经入库  根据批单申请号判断
        IssueRecordEntity issueRecordEntity = new IssueRecordEntity();
        issueRecordEntity.setApplicationFormCode(pdNo);
        List<IssueRecordEntity> select = issueRecordEntityMapper.select(issueRecordEntity);
        if (select != null && select.size() > 0) {
            log.info("系统时间：{}, 山东校责批单申请号是 {} 的消息发送重复", currentTime, pdNo);
            // 消息重复，消息直接消费完成。
            return true;
        }
        issueRecordEntity.setPolicyNo(policyNo);
        issueRecordEntity.setCompanyCode(companyCode);
        issueRecordEntity.setProCode(proCode);
        issueRecordEntity.setReqPacket(reqPacket.asXML());
        issueRecordEntity.setResPacket(respPacket.asXML());
        issueRecordEntity.setSendStatus("1");
        String status = respPacket.element("head").element("responseCode").getStringValue();
        if ("9200".equals(status)) {
            status = "2";
        } else {
            status = "3";
        }
        // 数据中心返回 的批单状态
        issueRecordEntity.setStatus(status);
        issueRecordEntity.setCreateTime(currentTime);
        issueRecordEntity.setUpdateTime(currentTime);
        issueRecordEntity.setIfCode(ifCode);
        issueRecordEntityMapper.insert(issueRecordEntity);
        if ("3".equals(status)) {
            // 出单失败，消息直接消费完成，在入库的逻辑后边。
            return true;
        }
        // 消费:从响应体中解析出 url，去调用数据中心的接口，下载电子批单
        IssuePolicyLogEntity issuePolicyLogEntity = new IssuePolicyLogEntity();
        String consumeStatus = "1";
        issuePolicyLogEntity.setApplicationFormCode(pdNo);
        issuePolicyLogEntity.setPolicyNo(policyNo);
        issuePolicyLogEntity.setType("2");
        issuePolicyLogEntity.setStatus(consumeStatus);
        issuePolicyLogEntity.setCreateTime(currentTime);
        issuePolicyLogEntity.setUpdateTime(currentTime);
        issuePolicyLogEntity.setProCode(proCode);
        String url = respPacket.element("body").element("apply").element("electricalDocument").getStringValue();
        // 拼装下载报文
        Document doc = DocumentHelper.createDocument();
        Element info = doc.addElement("body");
        info.addElement("url").addText(url);
        issuePolicyLogEntity.setParam(info.asXML());
        issuePolicyLogEntity.setTimes(0);
        issuePolicyLogEntity.setIfCode(ifCode);
        issuePolicyLogEntityMapper.insert(issuePolicyLogEntity);
        // 只要消息进入消费记录的库，就认为消费成功，修改消息记录表状态,具体有没有成功 记录在消费记录表，有定时任务。
        issueRecordEntity.setSendStatus("2");
        issueRecordEntityMapper.updateByPrimaryKeySelective(issueRecordEntity);
        //调用接口,请求数据交换中心，下载电子批单
        try {
            log.info("山东校责的批单申请号是 {}, 批单下载参数：{}", pdNo, info.asXML());
            // 请求下载批单，成功更新
            String seqNo = Long.toString(Math.abs(new Random().nextLong()));
            ResponseEntity<String> responseEntity = dexClient.text("edu", "20190516022", "1.0", seqNo, info.asXML());
            log.info("山东校责的批单申请号是 {}, 批单下载返回值：{}, {}", pdNo, responseEntity.getStatusCodeValue(), responseEntity.getBody());
            consumeStatus = "2";
            String fileId = responseEntity.getBody();
            issuePolicyLogEntity.setStatus(consumeStatus);
            // 下载成功，更新数据库，绑定资源
            log.info("山东校责 下载消息 fileId ：{}", fileId);
            bindingResources(pdNo, fileId, issuePolicyLogEntity);
            sendEmail(pdNo, "17", ifCode);
            return true;
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }




    /*
     * 解析返回响应报文xml
     * @param document 文档对象
     * @return 返回dom元素
     */

    /**
     * 山东批单相关邮件
     *
     * @param pdNo
     * @param type
     */
    public void sendEmail(String pdNo, String type, String ifCode) {
        //发送批单出单邮件
        log.info("--send sdpdEmail begin--" + pdNo);

        try {

            String genericListResponseResponseEntity = polClient.queryEndorsementDetailByApplyNo(pdNo);
            System.out.println(genericListResponseResponseEntity);
            JSONObject jsonObject = JSONObject.parseObject(genericListResponseResponseEntity);
            JSONObject data = jsonObject.getJSONObject("data");
            System.out.println("data=====>" + data);
            String applicationCode = data.getString("applicant");
            String applyNo2 = data.getString("applyNo");
            String endorsementsNo = data.getString("endorsementsNo");
            JSONObject head = data.getJSONObject("modifyAfterHolder");
            String linkEmail = head.getString("linkEmail");
            String startDate = data.getString("startDate");
            System.out.println("用户名" + applicationCode);
            System.out.println("批单申请号" + applyNo2);
            System.out.println("批单号" + endorsementsNo);
            System.out.println("收件人邮箱" + linkEmail);
            System.out.println("批单起期" + startDate);


//            String applicant = null;
//            String applyNo = null;
//            String endorsementsNo = null;
//            String linkEmail = null;
//            String startDate = null;
//            for (EduQueryEndorsementDetailVo eduInfo:EduQueryEndorsementDetailVoList) {
//                //批单申请人
//                applicant = eduInfo.getApplicant();
//                //批单申请号
//                applyNo = eduInfo.getApplyNo();
//
//                //批单号
//                endorsementsNo = eduInfo.getEndorsementsNo();
//                //邮箱
//                linkEmail = eduInfo.getModifyBeforeHolder().getLinkEmail();
//
//                //批单起期
//                startDate = eduInfo.getStartDate()+"";
//
//
//            }

//            MailDTO mailDTO = new MailDTO();
//            mailDTO.setNumber(applicant);
//            mailDTO.setProductName(IssueEnum.getProNameByIfCode(ifCode));
//            mailDTO.setCorrectNo(applyNo);
//            mailDTO.setPdStartDate(startDate);
//            mailDTO.setBatchNo(endorsementsNo);
//            mailDTO.setEmail(linkEmail);
//            emailsService.sendEmail(mailDTO, type);

        } catch (Exception e) {
            e.printStackTrace();
            log.error("根据批单号" + pdNo + "查询批单信息失败" + e);
        }

        log.info("--send sdpdEmail end--");
    }

    /*
     * 解析返回请求报文xml
     * @param document 文档对象
     * @return 返回dom元素
     */

    /*
     * 绑定资源，更新下载状态
     * @param applicationFormCode 批单申请号
     * @param fileId             文件id
     */
    public void bindingResources(String applicationFormCode, String fileId, IssuePolicyLogEntity issuePolicyLogEntity) throws Exception {
        String status = issuePolicyLogEntity.getStatus();
        if ("3".equals(status)) {
            issuePolicyLogEntity.setTimes(1);
            issuePolicyLogEntity.setEPolicyId(fileId);
            issuePolicyLogEntity.setStatus("3");
            issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);
        } else {


            try {
                //拼接绑定资源入参
                UploadEndorsementCheckFile uploadEndorsementCheckFile = new UploadEndorsementCheckFile();
                uploadEndorsementCheckFile.setApplyNo(applicationFormCode);
                uploadEndorsementCheckFile.setEndorseStatus("03");
                ArrayList<FileInfoVO> fileInfoVOS = new ArrayList<>();
                FileInfoVO fileInfoVO = new FileInfoVO();
                fileInfoVO.setFileName(applicationFormCode);
                fileInfoVO.setFileType("05");
                fileInfoVO.setFileUrl(fileId);
                fileInfoVOS.add(fileInfoVO);
                uploadEndorsementCheckFile.setFileInfoVO(fileInfoVOS);

                //调用批单中心绑定资源接口
                log.info(DateUtils.getCurrentTime() + "批单号 " + applicationFormCode + " 调用绑定资源接口开始，入参：" + JSON.toJSON(uploadEndorsementCheckFile));
                ResponseEntity<GenericListResponse<JsonObject>> genericListResponseResponseEntity = polClient.uploadEndorsementCheckFiles(uploadEndorsementCheckFile);
                GenericListResponse<JsonObject> body = genericListResponseResponseEntity.getBody();

                String code = body.getCode();
                log.info(DateUtils.getCurrentTime() + "批单号 " + applicationFormCode + " 调用绑定资源接口返回结果码" + code + ":" + body.getMsg());
                if (!"0000".equals(code)) {
                    issuePolicyLogEntity.setTimes(1);
                    issuePolicyLogEntity.setEPolicyId(fileId);
                    issuePolicyLogEntity.setStatus("3");
                    issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);
                } else {
                    issuePolicyLogEntity.setTimes(1);
                    issuePolicyLogEntity.setEPolicyId(fileId);
                    issuePolicyLogEntity.setStatus("2");
                    issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);
                }
            } catch (Exception e) {
                issuePolicyLogEntity.setTimes(1);
                issuePolicyLogEntity.setEPolicyId(fileId);
                issuePolicyLogEntity.setStatus("3");
                issuePolicyLogEntityMapper.updateByPrimaryKeySelective(issuePolicyLogEntity);
                log.error("调用绑定资源接口失败，请重新尝试");
            }
        }
    }

    public Element getRespPacket(Element rootElement) {
        Element respPacket = rootElement.element("respPacket");
        Element element = null;
        if (respPacket != null) {
            try {
                element = DocumentHelper.parseText(respPacket.getText()).getRootElement();
            } catch (DocumentException e) {
                e.printStackTrace();
                log.error("xml转义失败，生成xml错误", e);
            }
        }
        return element;
    }

    public Element getReqPacket(Element rootElement) {
        Element respPacket = rootElement.element("reqPacket");
        Element element = null;
        if (respPacket != null) {
            try {
                element = DocumentHelper.parseText(respPacket.getText()).getRootElement();
            } catch (DocumentException e) {
                e.printStackTrace();
                log.error("xml转义失败，生成xml错误", e);
            }
        }
        return element;
    }
}
